#include "ODN_ModelEntity.h"

#include "ODN_GameMgr.h"

//TODO: Replace this with Ogre resource loading
#define MODEL_PATH "models\\"

namespace ouden {

CModelEntity::CModelEntity(String sName) : CBaseEntity(sName)
{
    //& CRAPBLOCK
    m_pOgreEntity = CGameMgr::getInstance()->getSceneMgr()->createEntity("test", "robot.mesh");
    Ogre::SceneNode* pBotNode = CGameMgr::getInstance()->getSceneMgr()->getRootSceneNode()->
			createChildSceneNode("robot");
    pBotNode->scale(0.001,0.001,0.001);
    pBotNode->attachObject(m_pOgreEntity);
	m_pOgreEntity->setMaterialName("Plastic/Red"); //CRAP
	m_pOgreEntity->setNormaliseNormals(true); // Keep the normals normalized even after scaling.
    m_pOgreEntity->setVisible(true);
    std::cout << "hereME1" << std::endl;
    Ogre::SkeletonInstance* skeli = m_pOgreEntity->getSkeleton();

    m_pOgreEntity->_updateAnimation();
    simState = RAGDOLLING;
    std::cout << "hereME2" << std::endl;
    m_pRootBit = new CModelBit(skeli->getRootBone(), 0.002, NULL);

    /*REMOVE
    for(int i = 0; i < skeli->getNumBones(); i++) { //TODO: make sure proper version uses bone iterator
        bone = skeli->getBone(i);
        addBit(new CModelBit(bone,0.1,parent));    //TODO: remove magic number
    }*/

}

CModelEntity::CModelEntity(String sName, String sModelName) : CBaseEntity(sName)
{
	//ctor

	//Load blueprint
	//Load mesh
	//Load model entity description file
	//for each bit in model entity
	//  create model bit with new submesh and solid

	//TODO: Finish this function

	//Load the mesh into an Ogre entity
	m_pOgreEntity = CGameMgr::getInstance()->getSceneMgr()->createEntity(sName, sModelName + ".mesh");
	m_pOgreEntity->setMaterialName("Plastic/Red"); //CRAP
	m_pOgreEntity->setNormaliseNormals(true); // Keep the normals normalized even after scaling.

	//Load physics blueprint from file
	opal::Blueprint bpBlueprint;
	opal::loadFile(bpBlueprint, MODEL_PATH + sModelName + " blueprint.xml");
	opal::Matrix44r m44Transform;
	m44Transform.translate(0, 0, 0);

	//Instantiate the Blueprint.
	opal::BlueprintInstance bpiBlueprintInstance;
	//TODO: Look at scale factor or whatever 16 is for
	CGameMgr::getInstance()->getSimulator()->instantiateBlueprint(bpiBlueprintInstance, bpBlueprint, m44Transform, 16);

    /* REMOVE (probably with the rest of this constructor)
	if (m_pOgreEntity->hasSkeleton()) {

		//Get a pointer to the ogre skeleton
		Ogre::Skeleton* pSkeleton = pOgreEntity->getSkeleton();

		//Loop through the solids in the blueprint
		for (int i=0; i<bpiBlueprintInstance.getNumSolids(); ++i)
		{

			//Get the current solid
			opal::Solid* pSolid = bpiBlueprintInstance.getSolid(i);

			//Get the current bone
			Ogre::Bone* pBone = pSkeleton->getBone(pSolid->getName());

			//Create a new model bit
			CModelBit* pNewModelBit = new CModelBit(pSolid, pBone);
			m_pBits.push_back(pNewModelBit);

		}

	}
	else
	{

		//Get the only solid
		opal::Solid* pSolid = bpiBlueprintInstance.getSolid(0);

		//Create a new scenenode
		Ogre::SceneNode* pSceneNode = CGameManager::getInstance()->getSceneMgr()->getRootSceneNode()->
										createChildSceneNode(pSolid->getName());

		//Create a new model bit
		CModelBit* pNewModelBit = new CModelBit(pSolid, pSceneNode);
		m_pBits.push_back(pNewModelBit);

	}*/




}

CModelEntity::~CModelEntity()
{
	//dtor

    delete m_pRootBit;


}

void CModelEntity::changeSimState(SimulationState newState)
{

    simState = newState;

    if(simState == RAGDOLLING)  m_pCurrentAnimState->setEnabled(false);
    else m_pCurrentAnimState->setEnabled(true);

}

//TODO: check if this should be onTick or something instead
void CModelEntity::update()
{

    Array<CModelBit*>::iterator modelBit;

    if(simState == ANIMATING) {
    /*TODO: possibly need to disable joints on the ragdoll to make animation
    easier.
    Also consider whether it's best to simply use pure animation and disable the
    physical ragdoll until it's needed ie. in collision.
    */
        m_pOgreEntity->_updateAnimation();         // needed to make sure the skeleton updates, not necessarily called by Ogre

        /*REMOVE
        for(modelBit = m_pBits.begin(); modelBit != m_pBits.end(); modelBit++) {
            modelBit->snapSolidToNode();
        }*/
    }

    if(simState == BLENDING) {
    /*TODO: consider different ways of implementing the blending, ie. springs or
    direct manipulation, esp. think how it will affect stability and physical
    interaction
    */

        /*REMOVE
        for(modelBit = m_pBits.begin(); modelBit != m_pBits.end(); modelBit++) {
            modelBit->blendSolidToNode();
        }*/

    }

    if(simState == RAGDOLLING) {
    /*TODO: possibly disable animation
    */

        m_pRootBit->snapNodeToSolid();

    }

}


} //namespace ouden
